const vscode = require('vscode');
const fs = require('fs');
const path = require("path");

class Utils {
    constructor() { 
        // this.user1 = null;
        // this.user2 = null;
        // this.ready1 = false;
        // this.ready2 = false;
        // this.ws = null;
        this.variables = {};
        this.matchesKey = [];
    }
    getHtmlContext(context, filepath, form) {
        var text = fs.readFileSync(context.extensionPath + filepath, form);
        return text;
    }
    getOOO(filepath, form) {
        var text = fs.readFileSync(filepath, form);
        return text;
    }
    getVsFilePath(dirpath, filepath, context) {
        return vscode.Uri.file(path.join(context.extensionPath, dirpath, filepath));
    }
    getWebUrlPath(dirpath, filepath, context, panel) {
        return panel.webview.asWebviewUri(this.getVsFilePath(dirpath, filepath, context));
    }
    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    async showRecentInputQuickPick(string, path) {
        let recentBuildInputs = this.loadRecentBuildInputs(path);
        const inputCounts = {};
    
        const recentBuildInputsLimited = recentBuildInputs.slice(-10);
    
        const recentInputItems = recentBuildInputsLimited.map((input) => {
            return { label: input };
        });
    
        const quickPick = vscode.window.createQuickPick();
        quickPick.items = recentInputItems;
        quickPick.canPickMany = false;
        quickPick.placeholder = string;
        //quickPick.ignoreFocusOut = true;
        quickPick.value = recentBuildInputs[0];
    
        const selectedInput = await new Promise((resolve) => {
            quickPick.onDidChangeValue((value) => {
                quickPick.items = recentBuildInputsLimited
                    .filter((input) => input.includes(value))
                    .map((input) => {
                        return { label: input };
                    });
            });
    
            quickPick.onDidAccept(() => {
                resolve(quickPick.selectedItems[0]?.label ?? quickPick.value);
                quickPick.hide();
            });
    
            quickPick.show();
        });
    
        if (selectedInput) {
            if (!recentBuildInputs.includes(selectedInput)) {
                recentBuildInputs.push(selectedInput);
            }
    
            if (recentBuildInputs.length > 10) {
                const removedInput = recentBuildInputs.shift();
                delete inputCounts[removedInput];
            }
    
            inputCounts[selectedInput] = (inputCounts[selectedInput] || 0) + 1;
            this.saveRecentBuildInputs(recentBuildInputs, path);
        }
        return selectedInput ?? '';
    }
    loadRecentBuildInputs(path) {
        const filePath = path;
        if (fs.existsSync(filePath)) {
            return fs.readFileSync(filePath, 'utf8').split('\n');
        } else {
            return [];
        }
    }
    saveRecentBuildInputs(recentBuildInputs, path) {
        const filePath = path;
        fs.writeFileSync(filePath, recentBuildInputs.join('\n'), { encoding: 'utf8', mode: 0o777 });
    }
    async findTCDMPFiles(str) {
        const filePattern = str;
        const uriArray = await vscode.workspace.findFiles(filePattern);
        //uriArray.forEach(uri => console.log(uri.fsPath));
        return uriArray;
    }
    async selectTCDMPFile(str) {
        const uriArray = await this.findTCDMPFiles(str);
        const items = uriArray.map(uri => ({ label: uri.fsPath }));
        const selectedItem = await vscode.window.showQuickPick(items, {
            ignoreFocusOut: true,
            placeHolder: '��ѡ���ļ�'
        });
        return selectedItem ? vscode.Uri.file(selectedItem.label) : null;
    }
    infoReg(str) {
        const infoRegex = /^(\w+)\s*=\s*((?:\{[\s\S]*?\})|(?:[\w.,]+))/gm;
        const variables = {};
        let infoMatch;
        while ((infoMatch = infoRegex.exec(str)) !== null) {
            const [_, name, value] = infoMatch;
            variables[name] = this.parseValue(value);
        }
        console.log('variables:', variables);
        return variables;
    }
    parseValue(value) {
        if (value.startsWith('{')) {
            const trimmedValue = value.slice(1, -1).trim();
            if (trimmedValue === "") {
                return [];
            }
            const arrayValues = trimmedValue.split(',');
            const parsedArray = [];
            let isEllipsis = false;
    
            for (let i = 0; i < arrayValues.length; i++) {
                const arrayValue = arrayValues[i].trim();
                if (arrayValue.endsWith("...")) {
                    isEllipsis = true;
                    const startIndex = parseInt(arrayValue, 10);
                    const endIndex = arrayValues[arrayValues.length - 1].trim().replace("...", "");
                    for (let j = startIndex; j <= parseInt(endIndex, 10); j++) {
                        parsedArray.push(j);
                    }
                    break;
                } else {
                    parsedArray.push(this.parseValue(arrayValue));
                }
            }
    
            if (!isEllipsis) {
                return parsedArray;
            }
            return parsedArray.join(", ");
        } else if (value.startsWith('"') && value.endsWith('"')) {
            return value.slice(1, -1);
        } else if (value.startsWith('0x')) {
            return parseInt(value, 16);
        } else if (value.includes(',')) {
            return value.split(',').map(s => this.parseValue(s.trim()));
        } else {
            return isNaN(parseFloat(value)) ? value : parseFloat(value);
        }
    }
    bt(string) {
        const btRegex = /#(\d+)\s+((?:0x)?[\da-f]+)\s+in\s+(\w+) \(([^)]+)\)(?:\sat\s([^:]+):(\d+))?/gm;
        const btMatches = [];
    
        let btMatch;
        while ((btMatch = btRegex.exec(string)) !== null) {
            const [_, num, addr, name, args, file, line] = btMatch;
            const fileInfo = file && line ? [file, line] : ['', ''];
            if (!name && !args) {
                btMatches.push([`${addr} in ?? ()`, '', '']);
            } else {
                btMatches.push([`${addr} in ${name} (${args})`, ...fileInfo]);
            }
        }
        return btMatches;
    }
}

module.exports = { Utils };